//
//  QRCodeViewController.swift
//  HJWeibo
//
//  Created by huangjiong on 16/2/2.
//  Copyright © 2016年 huangjiong. All rights reserved.
//

import UIKit
import AVFoundation

class QRCodeViewController: UIViewController,UITabBarDelegate {
    
    //底部的tabBar
    @IBOutlet weak var customTabBar: UITabBar!
    //冲击波
    @IBOutlet weak var scanLine: UIImageView!
    //容器高度的约束
    @IBOutlet weak var containerHeightCons: NSLayoutConstraint!
    //冲击波与容器顶部的约束
    @IBOutlet weak var scanLineTopCons: NSLayoutConstraint!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //默认选中第0个,即二维码扫描
       customTabBar.selectedItem = customTabBar.items![0]
        customTabBar.delegate = self
    }
    
    // MARK: - 关闭菜单
    @IBAction func closeBtnClick(sender: AnyObject) {
        
        dismissViewControllerAnimated(true, completion: nil)
    }


    //MARK: - 视图即将出现时开始扫描
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        
        //1.开始冲击波动画
        startAnimation()
        
        //2.开始扫描
        startScan()
    }
    
    //MARK: - 冲击波动画
    private func startAnimation()
    {
        self.scanLineTopCons.constant = -self.containerHeightCons.constant
        //强制更新
        self.view.layoutIfNeeded()
        
        //执行冲击波动画
        UIView.animateWithDuration(2.0) { () -> Void in
            
            //修改约束
            self.scanLineTopCons.constant = self.containerHeightCons.constant
            UIView.setAnimationRepeatCount(MAXFLOAT)
            self.view.layoutIfNeeded()
        }

    }
    
    //MARK: - 扫描
    private func startScan()
    {
        //1.先处理不能添加输入设备和输入数据的情况
        if !session.canAddInput(deviceInput) || !session.canAddOutput(outputData)
        {
            return
        }
        
        //2.将输入,输出添加到会话中
        session.addInput(deviceInput)
        session.addOutput(outputData)
        
        //3.设置输出数据类型,此处设成所有能够解析的类型
        outputData.metadataObjectTypes = outputData.availableMetadataObjectTypes
        
        //4.设置输出代理,以及解析数据的线程
        outputData.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
        
        //5.添加预览图层
        view.layer.insertSublayer(previewLayer, atIndex: 0)
        
        //6.将边线的父图层drawLayer添加到预览图层上
        previewLayer.addSublayer(drawLayer)
        
        //7.让session开始扫描,如果扫描到数据,就会不断调用代理方法进行解析
        session.startRunning()
    }
    
    
    // MARK: - UITabBarDelegate,用于切换二维码扫描,以及条形码扫描
    func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
        
        //1.停止动画
        scanLine.layer.removeAllAnimations()
        //2.修改约束
        if item.tag == 1
        {
            self.containerHeightCons.constant = 300
        }
        else
        {
            self.containerHeightCons.constant = 150
        }
        //3.重新开始动画
        startAnimation()
    }
    
    
    
    
    
    //**************   扫描所需要的对象,定义成懒加载的属性     *************//
    //MARK: - 懒加载用于扫描的几个属性,注意先导入框架import AVFoundation
    //1.会话
    private lazy var session:AVCaptureSession = AVCaptureSession()
    //2.输入设备,此处是摄像头
    private lazy var deviceInput: AVCaptureDeviceInput? = {
        //获取摄像头,再将摄像头包装成我们要的输入设备类型
        let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        //注意系统规定要处理异常情况
        do{
            let tempDeviceInput = try AVCaptureDeviceInput(device: device)
            
            return tempDeviceInput
        } catch
        {
            print(error)
            return nil
        }
    }()
    //3.输出数据
    private lazy var outputData: AVCaptureMetadataOutput = AVCaptureMetadataOutput()
    //4.预览图层
    private lazy var previewLayer: AVCaptureVideoPreviewLayer = {
        //要指定一个会话对象
        let layer = AVCaptureVideoPreviewLayer(session: self.session)
        layer.frame = UIScreen.mainScreen().bounds
        return layer
    }()
    
    //5.再定义一个属性,当作绘制边线的父图层
    private lazy var drawLayer: CALayer = {
        let layer = CALayer()
        layer.frame = UIScreen.mainScreen().bounds
        return layer
    }()
   //*********************************************************************//
    
    
}



//扫描输出代理
extension QRCodeViewController:AVCaptureMetadataOutputObjectsDelegate
{
    
    /**
     一.解析数据的代理方法,只要是解析到了数据,就会不断调用
     
     - parameter captureOutput:   <#captureOutput description#>
     - parameter metadataObjects: <#metadataObjects description#>
     - parameter connection:      <#connection description#>
     */
    func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
        
        //0.先移除上一次绘制的边线
        clearLine()
        
        //1.遍历获取到的所有数据
        for object in metadataObjects
        {
            //1.1先判断当前数据是否为机器可为别的类型
            if object is AVMetadataMachineReadableCodeObject
            {
                //1.2将当前数据转换,主要是将其中的坐标信息,转换成预览图层可识别的坐标
                let codeObject = previewLayer.transformedMetadataObjectForMetadataObject(object as! AVMetadataObject) as! AVMetadataMachineReadableCodeObject
                //1.3利用转换后的数据,进行边线的绘制
                drawLine(codeObject)
            }
        }
    }
    
    
    /**
     二.自定义方法,用于绘制二维码的边线
     
     - parameter codeObject: <#codeObject description#>
     */
    private func drawLine(codeObject:AVMetadataMachineReadableCodeObject)
    {
        if codeObject.corners.isEmpty
        {
            return
        }
        
        //1.创建一个图层
        let layer = CAShapeLayer()
        layer.lineWidth = 3
        layer.strokeColor = UIColor.redColor().CGColor
        layer.fillColor = UIColor.clearColor().CGColor
        
        //2.创建一个贝赛尔路径
        let path = UIBezierPath()
        var point = CGPointZero
        var index: Int = 0
        //2.1定位到第0个点
        //下面这方法,是将第index个点的坐标取出来存放point中
        CGPointMakeWithDictionaryRepresentation((codeObject.corners[index] as! CFDictionaryRef), &point)
        path.moveToPoint(point)
        //2.2依次移动到下一个点
        while index < codeObject.corners.count
        {
            CGPointMakeWithDictionaryRepresentation((codeObject.corners[index] as! CFDictionaryRef), &point)
            path.addLineToPoint(point)
            index++
        }
        //2.3关闭路径
        path.closePath()
        
        //3.绘制路径
        layer.path = path.CGPath
        
        //4.将绘制好的图层,添加到drawLayer上
        drawLayer.addSublayer(layer)
    }
    
    
    /**
     三.自定义一个方法,用于清除上一次绘制的边线
     */
    private func clearLine()
    {
        //1.先判断是否有其他子图层
        if drawLayer.sublayers == nil || drawLayer.sublayers?.count == 0
        {
            return
        }
        
        //2.移除所有子图层
        for subLayer in drawLayer.sublayers!
        {
            subLayer.removeFromSuperlayer()
        }
    }
    
    
}
